package apps

import (
	"news/pkg/apps/ctx"
	"news/pkg/services"
	"news/pkg/types"
	"news/pkg/types/errors"
	"time"
)

func UserRegister(c *ctx.Context, form *types.UserRegisterForm) (interface{}, error) {
	user, err := services.CreateUser(c.DB(), form)
	if err != nil {
		return nil, err
	}
	c.Logger().Infof("created user: %s(%s)", user.Username, user.Id)

	return types.GetUserResp{
		Id:        user.Id,
		Username:  user.Username,
		Password:  user.Password,
		Role:      user.Role,
		HeadImg:   user.HeadImg,
		Age:       user.Age,
		Sex:       user.Sex,
		Desc:      user.Desc,
		CreatedAt: user.CreatedAt,
	}, nil
}

func UserLogin(c *ctx.Context, form *types.UserLoginForm) (interface{}, error) {
	lg := c.Logger()

	user, err := services.GetUserByName(c.DB(), form.Username)
	if err != nil {
		if errors.IsNotFoundErr(err) {
			return nil, errors.ErrAuthFailed
		}
		return nil, err
	}

	// 验证token by cloudiac api
	ok, err := services.VerifyUserPassword(form.Password, user.Password)
	if err != nil {
		lg.Errorf("verify user password: %v", err)
		return nil, err
	}
	if !ok {
		return nil, errors.ErrAuthFailed
	}

	// 发行自己的 jwt token
	token, err := services.GenerateJwtToken(user.Id, user.Username, 24*time.Hour)
	if err != nil {
		lg.Errorf("SsoLogin -> GenerateJwtToken: %s", err.Error())
		return nil, err
	}

	return &types.UserLoginResp{
		Token: token,
		User: types.GetUserResp{
			Id:        user.Id,
			Username:  user.Username,
			Password:  user.Password,
			Role:      user.Role,
			HeadImg:   user.HeadImg,
			Age:       user.Age,
			Sex:       user.Sex,
			Desc:      user.Desc,
			CreatedAt: user.CreatedAt,
		},
	}, nil
}

func SearchUser(c *ctx.Context, form *types.SearchUserForm) (interface{}, error) {
	query := services.QueryUser(c.DB(), form.Q)
	users := make([]types.GetUserResp, 0)

	if err := query.Find(&users).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return c.PageResult(query, form.Page(), form.PageSize(), &users)
}

func AuthMe(c *ctx.Context) (interface{}, error) {
	userInfo, userErr := c.User()
	if userErr != nil {
		return nil, userErr
	}
	user, err := services.GetUserById(c.DB(), userInfo.Id)
	if err != nil {
		return nil, err
	}
	return types.GetUserResp{
		Id:        user.Id,
		Username:  user.Username,
		Password:  user.Password,
		Role:      user.Role,
		HeadImg:   user.HeadImg,
		Age:       user.Age,
		Sex:       user.Sex,
		Desc:      user.Desc,
		CreatedAt: user.CreatedAt,
	}, nil
}

func DeleteUsers(c *ctx.Context, form *types.UsersDeleteForm) (interface{}, error) {
	user, userErr := c.User()
	if userErr != nil {
		return nil, userErr
	}
	userInfo, userInfoErr := services.GetUserById(c.DB(), user.Id)
	if userInfoErr != nil {
		return nil, userInfoErr
	}
	if userInfo.Role != "admin" {
		return nil, errors.ErrNotAuth
	}
	err := services.DeleteUsers(c.DB(), form.UserIds)
	if err != nil {
		return nil, err
	}
	return nil, nil
}

func DeleteUser(c *ctx.Context, form *types.DeleteUserForm) (interface{}, error) {
	userinfo, err := c.User()
	if err != nil {
		return nil, err
	}
	//删之前确认一下id是否存在
	_, userCheckErr := services.GetUserById(c.DB(), form.UserId)
	if userCheckErr != nil {
		return nil, userCheckErr
	}
	//如果删除用户不是自己（注销），则判断是否为管理员权限
	if userinfo.Id != form.UserId {
		//判断是否有删除权限
		err := services.HasDeleteUserPerm(c.DB(), userinfo.Id)
		if err != nil {
			return nil, err
		}
	}
	if err = services.DeleteNewsByUserId(c.DB(), form.UserId); err != nil {
		return nil, errors.AutoDbErr(err)
	}
	errInfo := services.DeleteUser(c.DB(), form.UserId)
	if errInfo != nil {
		return nil, errInfo
	}
	return nil, nil
}

func UpdateUser(c *ctx.Context, form *types.UpdateUserForm) (interface{}, error) {
	userInfo, err := services.GetUserById(c.DB(), form.UserId)
	if err != nil {
		return nil, err
	}
	form.Role = userInfo.Role
	form.Password = userInfo.Password
	user, errInfo := services.UpdateUser(c.DB(), form)
	if errInfo != nil {
		return nil, errInfo
	}
	return types.GetUserResp{
		Id:        user.Id,
		Username:  user.Username,
		Password:  user.Password,
		Role:      user.Role,
		HeadImg:   user.HeadImg,
		Age:       user.Age,
		Sex:       user.Sex,
		Desc:      user.Desc,
		CreatedAt: user.CreatedAt,
	}, nil
}

func UpdateUserPassword(c *ctx.Context, form *types.UpdateUserPassword) (interface{}, error) {
	lg := c.Logger()
	user, err := services.GetUserById(c.DB(), c.MustUser().Id)
	if err != nil {
		return nil, err
	}
	ok, verifyErr := services.VerifyUserPassword(form.OldPass, user.Password)
	if verifyErr != nil {
		lg.Errorf("verify user password: %v", verifyErr)
		return nil, verifyErr
	}
	if !ok {
		return nil, errors.ErrAuthFailed
	}
	userInfo, updateErr := services.UpdatePass(c.DB(), form)
	if updateErr != nil {
		return nil, updateErr
	}
	return types.PassUpdateResp{
		Id:       userInfo.Id,
		Role:     userInfo.Role,
		Username: userInfo.Username,
	}, nil
}

func AdminUpdate(c *ctx.Context, form *types.AdminUpdate) (interface{}, error) {
	loginUser, err := services.GetUserById(c.DB(), c.MustUser().Id)
	if err != nil {
		return nil, err
	}
	if loginUser.Role != "admin" {
		return nil, errors.ErrNotAuth
	}
	user, updateErr := services.AdminUpdate(c.DB(), form)
	if updateErr != nil {
		return nil, updateErr
	}
	return types.PassUpdateResp{
		Id:       user.Id,
		Role:     user.Role,
		Username: user.Username,
	}, nil
}
